<?php
/**
 * CopyGoodsToPdd.php class file.
 * @author wudg <544038230@qq.com>
 * @date 2020/12/16- 上午11:13
 */

namespace common\jobs\copy;

use common\dao\PddMallLogisticsDao;
use common\helpers\UrlsHelper;
use common\constants\CopyConst;
use common\constants\ProductConst;
use common\exception\JumpException;
use common\helpers\CopyHelper;
use common\jobs\dao\PddCopyLogDao;
use common\jobs\dao\PddCopyProductsDao;
use common\exception\CopyException;
use common\jobs\copy\tools\PddFilterBasic;
use common\jobs\copy\tools\PddPreset;
use common\jobs\copy\tools\PddSku;
use common\jobs\models\PddFilterTpl;
use common\jobs\services\CopyService;
use common\jobs\copy\tools\PddFilterJump;
use common\jobs\copy\tools\PddSpec;
use common\components\api\isv\Goods;
use common\components\misc\ImportLogger;
use common\constants\PlatformConst;
use common\drivers\interfaces\JobInterface;
use common\exception\ServicesException;
use common\exception\TaskException;
use common\helpers\AmountHelper;
use common\helpers\ImagesHelper;
use common\helpers\StringHelper;
use common\models\com\ComSpider;
use Swoole\Coroutine\WaitGroup;
use yii\base\Exception;
use common\exception\JobException;
use console\components\helpers\ConsoleHelper;
use Yii;
use yii\base\ErrorException;
use yii\helpers\ArrayHelper;
use yii\helpers\FileHelper;

/**
 * 拼多多上货任务
 * Class CopyGoodsToPdd
 * @package api\task\copy
 */
class CopyGoodsToPdd extends CopyBase implements JobInterface
{

    /**
     * 参数组装
     * @var array
     */
    public $args = [];


    /**
     * 价格倍数不一致，重试10次数
     * @var int
     */
    public $retryTimes = 10;

    /**
     * 水印图片宽度
     * @var int
     */
    private $avatarWidth = 200;

    /**
     * 水印图片高度
     * @var int
     */
    private $avatarHeight = 80;


    /**
     * 过滤规则信息
     * @var PddFilterTpl
     */
    public $filter = null;


    /**
     * 请求isv 服务
     * @var Goods
     */
    public $goodsIsv;


    /**
     * 复制相关服务
     * @var CopyService
     */
    public $copyServer;


    /**
     * 源数据
     * @var ComSpider
     */
    public $sourceData = null;


    /**
     * 复制数据
     * @var array
     */
    public $copyData = [];


    /**
     * 主图水印
     * @var null
     */
    public $mainWater = null;


    /**
     * 详情图水印
     * @var null
     */
    public $detailWater = null;


    /**
     * sku 规格树
     * @var array
     */
    public $skuDataTree = [];


    /**
     * 获取异步任务执行需要的参数
     * SyncProduct constructor.
     * @param array $args
     */
    public function __construct(array $args = [])
    {
        $this->args = $args;

        $this->cacheSuccessKey .= $this->args['batch_id'];
        $this->cacheErrorKey .= $this->args['batch_id'];
        $this->totalCacheKey .= $this->args['batch_id'];

    }


    /**
     * 处理队列
     * @inheritDoc
     * @since 复制后的商品状态判断bug 修复 2021-01-30 by wudg
     * @return mixed|void
     */
    public function handle()
    {

        try {
            ConsoleHelper::runInfo($this->args['spider_id'] . ':copy:');
            $this->logger = new ImportLogger($this->_createFilePath());
            Yii::$app->db->open();

            $this->batchInfo = (new PddCopyLogDao())->getBatchInfoByPk($this->args['batch_id']);

            if (!$this->batchInfo) {
                throw new CopyException('批次号不存在');
            }


            $this->logInfo = (new PddCopyProductsDao())->getInfoByPk($this->args['log_id']);

            if (!$this->logInfo) {
                throw new CopyException('日志不存在');
            }

            //取消跳过
            if ($this->logInfo->status == CopyConst::COPY_CANCEL) {
                throw new JobException('任务已取消');
            }

            $spiderContent = ComSpider::findOne(['id' => $this->args['spider_id']]);


            if (!$spiderContent) {
                throw new CopyException('复制源数据不存在');
            }
            $this->sourceData = $spiderContent;
            $this->copyServer = new CopyService();

            $this->goodsIsv = new Goods();

            $this->sourceData->extend_data = json_decode($this->sourceData->extend_data, true);
            //获取上家最低和最高价格
            $this->source_min_price = $this->sourceData->extend_data['prices'];
            $this->source_max_price = $this->sourceData->extend_data['prices'];
            $this->postage = isset($this->sourceData->extend_data['postage'])?$this->sourceData->extend_data['postage']:0;
            if (isset($this->sourceData->extend_data['skus'])&&!empty($this->sourceData->extend_data['skus'])) {
                foreach($this->sourceData->extend_data['skus'] as $k =>$v){
                    if ($v['price'] * 100 > $this->source_max_price) {
                        $this->source_max_price = $v['price'] * 100;
                    }
                }

            }

            $filterInfo = PddFilterTpl::findOne(['id' => $this->args['filter_id']]);
            if (!$filterInfo) {
                throw new CopyException('搬家配置不存在');
            }
            $filterInfo->settings = json_decode($filterInfo->settings, 1);

            $this->filter = $filterInfo;
            //先设定好日志表相关记录
            $this->logInfo->source_mall_name = $this->sourceData->extend_data['mall_name'] ?? '';
            if (!$this->logInfo->title) {
                $this->logInfo->title = $this->sourceData->extend_data['title'] ?? '';
            }
            $this->logInfo->main_pic = $this->sourceData->extend_data['main_pic'] ?? '';
            /**
             * 跳过设置
             */
            $this->filter();
            /**
             * 基础设置
             */
            $this->basicSetting();

            /**
             * 复制到店铺
             */
            $result = $this->copy();
            if (!$result) {
                throw new CopyException('系统错误复制失败');
            }
            if ($result['goods_commit_id'] && $result['goods_id']) {
                $this->_showLog('复制成功->' . StringHelper::jsonEncode($result));
                $this->setSuccessNum();
                $source_url = UrlsHelper::getUrlBySourceAndPk(1, $this->sourceData->extend_data['num_iid']);
                //补充映射关系
                $commit = $this->goodsIsv->pddGoodsSetRelation( $result['goods_id'], $this->sourceData->extend_data['num_iid'],$source_url,$this->source_min_price,$this->source_max_price,$this->postage,0,$this->args['mall_id']);
                if($commit){

                    $this->_writeLog3('请求参数goods_id:'.$result['goods_id'].'外部商品ID'.$this->sourceData->extend_data['num_iid'].'外部url'.$source_url.'最低价'.$this->source_min_price.'最高价'.$this->source_max_price.'邮费'.$this->postage.'返回结果:'.json_encode($commit), '@runtime/api/setrelation/');
                }
                /**
                 * 执行到最后可能存在连接丢失情况
                 */
                if (!Yii::$app->db->isActive) {
                    Yii::$app->db->open();
                }
                $this->logInfo->copy_id = (string)$result['goods_id'];
                $this->logInfo->goods_commit_id = $result['goods_commit_id'];
                $copyStatus = @$this->filter->settings['basic']['copy_goods_status'];
                if ($copyStatus == 2) {
                    $saveData = [
                        'status' => CopyConst::COPY_YES,
                        'product_status' => ProductConst::ON_COMMIT,
                    ];
                } else {
                    $saveData = [
                        'status' => CopyConst::COPY_YES,
                        'product_status' => ProductConst::ON_SALES,
                    ];
                }
                $this->saveLog($saveData);
            } else {
                throw new CopyException('系统错误复制失败');
            }
            Yii::$app->db->close();
        } catch (TaskException $e) {
            $this->_showLog('任务异常->' . $e->getMessage());
            $this->setErrorNum();
            $this->logInfo->error_info = $e->getMessage();
            $this->saveLog([
                'status' => CopyConst::COPY_FAILED,
                'product_status' => 0
            ]);

        } catch (CopyException $e) {
            $this->_showLog('复制异常->' . $e->getMessage() . '文件地址->' . $e->getFile() . '文件行数->' . $e->getLine());
            $this->setErrorNum();
            $this->logInfo->error_info = $e->getMessage();
            $this->saveLog([
                'status' => CopyConst::COPY_FAILED,
                'product_status' => 0
            ]);

        } catch (ServicesException $e) {
            $this->_showLog('服务异常->' . $e->getMessage());
            $this->setErrorNum();
            $this->logInfo->error_info = $e->getMessage();
            $this->saveLog([
                'status' => CopyConst::COPY_FAILED,
                'product_status' => 0
            ]);

        } catch (ErrorException $e) {
            $this->_showLog('程序异常->' . $e->getMessage() . '错误文件：' . $e->getFile() . '错误行数' . $e->getLine());
            $this->setErrorNum();
            $this->logInfo->error_info = $e->getMessage();
            $this->saveLog([
                'status' => CopyConst::COPY_FAILED,
                'product_status' => 0
            ]);
        } catch (JumpException $e) {
            $this->_showLog('跳过异常->' . $e->getMessage() . '错误文件：' . $e->getFile() . '错误行数' . $e->getLine());
            $this->setErrorNum();
            $this->logInfo->error_info = $e->getMessage();
            $this->saveLog([
                'status' => CopyConst::COPY_FILTER,
                'product_status' => 0
            ]);
        } catch (JobException $e) {
            $this->_showLog($e->getMessage());
        } finally {
            Yii::$app->db->close();
        }


    }


    /**
     * 复制商品
     * @inheritDoc
     * @return array
     * @since 增加sku价格倍数原因导致上货失败的问题处理 by wudg 2021-01-31
     * @throws CopyException
     * @throws ServicesException
     */
    public function copy()
    {
        $this->_showLog('开始复制商品');
        $responseData = '';
        $this->logger->add($this->args['spider_id'] . ':copy:上货参数:' . StringHelper::jsonEncode($this->copyData));
        $copyStatus = @$this->filter->settings['basic']['copy_goods_status'];
        switch ($copyStatus) {
            case 2: //放入草稿箱
                $this->_showLog('复制到草稿箱');
//                $this->_writeLog(json_encode($this->copyData));
//                exit();
                $responseEditCommit = $this->goodsIsv->pddGoodsEditGoodsCommit($this->copyData, $this->args['mall_id']);
                if (!isset($responseEditCommit['goods_update_response'])) {
                    $subCode = @$responseEditCommit['error_response']['sub_code'];
                    $subMessage = @$responseEditCommit['error_response']['error_msg'];
                    if ($subCode) {
                        $responseData = $this->errorHandler($subCode, $copyStatus, $responseEditCommit, $subMessage);
                    }
                } else {
                    $responseData = $responseEditCommit['goods_update_response'];
                }
                break;
            default: //上货到店铺
                $responseCommit = $this->goodsIsv->pddGoodsAdd($this->copyData, $this->args['mall_id']);
                if (!isset($responseCommit['goods_add_response'])) {
                    $subCode = @$responseCommit['error_response']['sub_code'];
                    $subMessage = @$responseCommit['error_response']['error_msg'];
                    $responseData = $this->errorHandler($subCode, $copyStatus, $responseCommit, $subMessage);

                } else {
                    $responseData = $responseCommit['goods_add_response'];

                }
                break;
        }
        return $responseData;


        //检查下上货成功后的商品状态
//        if($response)
//        {
//            $responseCheck = $this->goodsIsv->pddGoodsCommitDetailGet($response['goods_commit_id'],$response['goods_id'],$this->args['mall_id']);
//
//
//            print_r($responseCheck); exit;
//        }
    }


    /**
     * 异常情况处理
     * @param string $errorCode
     * @param string $subMessage
     * @param int $copyStatus
     * @param array $responseError
     * @return array|mixed|null
     * @throws CopyException
     * @throws ServicesException
     */
    private function errorHandler(string $errorCode, int $copyStatus, array $responseError, string $subMessage)
    {
        $responseData = null;
        switch ($errorCode) {
            case 'isv.invalid-parameter:price-gap-is-over-range': //商品规格中价格的范围过大，请调整价格
                $responseData = $this->retrySkuPriceError($copyStatus);
                break;
            case '2000000': //规格值加和数量超过限制，请删除

                if ($subMessage == 'sku数量和规格乘积不一致' || $subMessage == '规格值加和数量超过限制，请删除') {
                    $responseData = $this->retrySkuMoreError($copyStatus);
                } else if ($subMessage == '部分sku的规格信息不完整') {
                    $responseData = $this->retrySkuLimitError($copyStatus);
                } else {
                    $this->_writeLog2(json_encode($this->copyData));
                    $errStr = $responseError['error_response']['error_msg'] ?? '请求服务异常';
                    throw new CopyException($errStr);
                }

                break;
            case '600123': //规格数目不可超过2
                $responseData = $this->retrySkuLimitTwo($copyStatus);
                break;
            case '100045': //该类目下假一罚十必须选否
                $responseData = $this->retryIsfolt($copyStatus);
                break;
            default:
                $this->_writeLog2(json_encode($this->copyData));
                $errStr = $responseError['error_response']['error_msg'] ?? '请求服务异常';
                throw new CopyException($errStr);
        }
        return $responseData;
    }

    /**
     * 假一罚十必须选否
     * @param int $copyStatus
     * @return mixed|null
     * @throws CopyException
     * @throws ServicesException
     */
    private function retryIsfolt(int $copyStatus)
    {
        $this->copyData['is_folt'] = 'false';
        if ($copyStatus == 2) {
            $responseCommit = $this->goodsIsv->pddGoodsEditGoodsCommit($this->copyData, $this->args['mall_id']);
            if (!isset($responseCommit['goods_update_response'])) {
                $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                ConsoleHelper::runInfo('假一罚十必须选否失败');
                throw new CopyException($errStr);
            }
            $responseData = $responseCommit['goods_update_response'];
        } else {
            $responseCommit = (new Goods())->pddGoodsAdd($this->copyData, $this->args['mall_id']);
            if (!isset($responseCommit['goods_add_response'])) {
                $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                ConsoleHelper::runInfo('假一罚十必须选否失败');
                throw new CopyException($errStr);
            }
            $responseData = $responseCommit['goods_add_response'];
        }
        if ($responseData == null) {
            throw new CopyException('假一罚十必须选否失败');
        }
        return $responseData;
    }

    /**
     * sku 规格数目不可超过2
     * @param int $copyStatus
     * @return mixed|null
     * @throws CopyException
     * @throws ServicesException
     */
    private function retrySkuLimitTwo(int $copyStatus)
    {
        $specInfo = $this->copyServer->getSpecByCid($this->copyData['cat_id'], $this->args['mall_id']);

        $skuMapInfo = $this->goodsIsv->pddGoodsSpecGet($this->copyData['cat_id'], $this->args['mall_id']);

        /**
         * sku别名适配
         */
        $aliasSkuList = PddSpec::skuValueSettings($this->sourceData->extend_data['skus'], $this->filter->settings['sku']);

        /**
         * 处理源数据sku 信息
         */
        $tripSkuImg = PddSpec::tripSkuImg($this->sourceData->extend_data['sku_img']);
        $tripSkuList = PddSpec::tripSkuList($aliasSkuList);
        if ($tripSkuList) {
            foreach ($tripSkuList as $k => $v) {
                $tripSkuList[$k]['properties_name'] = json_decode($tripSkuList[$k]['properties_name'], true);
            }
        }
        if ($tripSkuList) {
            foreach ($tripSkuList as $k => $v) {
                if ($v['properties_name']) {
                    $properties_count = count($v['properties_name']);
                    while ($properties_count > 2) {
//                        $maxTwosmall = PddSpec::getMaxSmallTwo($tripSkuList[$k]['properties_name']);
//                        $a = explode(':', $maxTwosmall['min']['word']);
//                        $tripSkuList[$k]['properties_name'][$maxTwosmall['min']['key']] = $tripSkuList[$k]['properties_name'][$maxTwosmall['max']['key']] . $a[1];
//                        unset($tripSkuList[$k]['properties_name'][$maxTwosmall['max']['key']]);
//                        $arr = array();
//                        foreach ($tripSkuList[$k]['properties_name'] as $k1 => $v1) {
//                            $arr[] = $v1;
//                        }
//                        $tripSkuList[$k]['properties_name'] = $arr;
                        $a = explode(':', $tripSkuList[$k]['properties_name'][0]);
                        $tripSkuList[$k]['properties_name'][0] = $tripSkuList[$k]['properties_name'][1] . $a[1];
                        unset($tripSkuList[$k]['properties_name'][1]);
                        $arr = array();
                        foreach ($tripSkuList[$k]['properties_name'] as $k1 => $v1) {
                            $arr[] = $v1;
                        }
                        $tripSkuList[$k]['properties_name'] = $arr;
                        $properties_count--;
                    }
                    $tripSkuList[$k]['properties_name'] = json_encode($tripSkuList[$k]['properties_name'], JSON_UNESCAPED_UNICODE);
                }
            }
        }
        $skuData = PddSpec::getSkuBySkuList($tripSkuList, $tripSkuImg);

        $this->copyData['goods_properties'] = [];
        if ($specInfo) {
            list($parentSpecList, $childSpecList) = PddSpec::getPropsParentAndChild($specInfo['properties']);

            /**
             * 非销售属性适配
             */
            $properties = $this->_notSalesTolerant($parentSpecList, $childSpecList);

            /**
             * 最后拼装非销售属性参数
             */
            foreach ($properties as $p => $prop) {
                $tmp = [];
                $tmp['ref_pid'] = $prop['ref_pid'];
                $tmp['value'] = $prop['value'];
                if ($prop['vid']) {
                    $tmp['vid'] = $prop['vid'];
                }
                //属性模板id
                $tmp['template_pid'] = $prop['template_pid'];
                //存在上级属性
//            if(isset($prop['parent_spec_id']))
//            {
//                $tmp['parent_spec_id'] = $prop['parent_spec_id'];
//            }
                if (!empty($prop['value_unit'])) {
                    $tmp['value_unit'] = $prop['value_unit'];
                }
                array_push($this->copyData['goods_properties'], $tmp);
            }
        }
        $this->copyData['goods_properties'] = StringHelper::jsonEncode($this->copyData['goods_properties']);


        /**
         * 销售属性适配
         */
        $skuData = $this->_salesProp($skuData, $skuMapInfo);

        $this->skuDataTree = $skuData;
        /**
         * 销售属性，适配sku
         */
        $this->_setSku($skuData, $tripSkuList);
        if ($copyStatus == 2) {
            $this->logger->add($this->args['spider_id'] . ':copy-skulimit2:上货参数:' . StringHelper::jsonEncode($this->copyData));
            $responseCommit = $this->goodsIsv->pddGoodsEditGoodsCommit($this->copyData, $this->args['mall_id']);
            if (!isset($responseCommit['goods_update_response'])) {
                $subCode = @$responseCommit['error_response']['sub_code'];
                if (isset($subCode)) {
                    $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                    if ($errStr == 'sku数量和规格乘积不一致' || $errStr == '部分sku的规格信息不完整' || $errStr == '规格值加和数量超过限制，请删除') {
                        ;
                        $responseCommit = $this->errorHandler($responseCommit['error_response']['sub_code'], $copyStatus, $responseCommit, $errStr);
                        if (isset($responseCommit['goods_commit_id'])) {
                            return $responseCommit;
                        }
                    } else {
                        throw new CopyException($errStr);
                    }
                }
                ConsoleHelper::runInfo('sku 规格数目不可超过2报错合并sku失败');

            }
            $responseData = $responseCommit['goods_update_response'];
        } else {
            $this->logger->add($this->args['spider_id'] . ':copy-skulimit2:上货参数:' . StringHelper::jsonEncode($this->copyData));
            $responseCommit = (new Goods())->pddGoodsAdd($this->copyData, $this->args['mall_id']);
            if (!isset($responseCommit['goods_add_response'])) {
                $subCode = @$responseCommit['error_response']['sub_code'];
                if (isset($subCode)) {
                    $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                    if ($errStr == 'sku数量和规格乘积不一致' || $errStr == '部分sku的规格信息不完整' || $errStr == '规格值加和数量超过限制，请删除') {
                        ;
                        $responseCommit = $this->errorHandler($responseCommit['error_response']['sub_code'], $copyStatus, $responseCommit, $errStr);
                        if (isset($responseCommit['goods_commit_id'])) {
                            return $responseCommit;
                        }
                    } else {
                        throw new CopyException($errStr);
                    }
                }
                ConsoleHelper::runInfo('sku 规格数目不可超过2报错合并sku失败');
            }
            $responseData = $responseCommit['goods_add_response'];
        }
        if ($responseData == null) {
            throw new CopyException('sku 规格数目不可超过2报错合并sku失败');
        }
        return $responseData;

    }


    /**
     * sku 乘积和超限错误补救措施
     * @param int $copyStatus
     * @return mixed|null
     * @throws CopyException
     * @throws ServicesException
     */
    private function retrySkuMoreError(int $copyStatus)
    {
        $responseData = null;
        $tryTimes = 0;
        $skuListArr = StringHelper::jsonDecode($this->copyData['sku_list']);
        while ($tryTimes <= $this->retryTimes) {
            list($skuListArr, $this->skuDataTree) = PddSku::reduceSkuData($skuListArr, $this->skuDataTree);
            $this->copyData['sku_list'] = StringHelper::jsonEncode($skuListArr);
            if ($copyStatus == 2) {
                $this->logger->add($this->args['spider_id'] . ':copy-cjcx-' . ($tryTimes) . ':上货参数:' . StringHelper::jsonEncode($this->copyData));
                $responseCommit = $this->goodsIsv->pddGoodsEditGoodsCommit($this->copyData, $this->args['mall_id']);
                if (!isset($responseCommit['goods_update_response'])) {
                    $subCode = @$responseCommit['error_response']['sub_code'];
                    if (isset($subCode) && $subCode != '2000000') {
                        $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                        throw new CopyException($errStr);
                    }
                    ConsoleHelper::runInfo('上货草稿箱,删除部分sku后失败，并重试第' . ($tryTimes) . '次');
                    $tryTimes++;
                    sleep(1);
                    continue;
                }
                $responseData = $responseCommit['goods_update_response'];
                break;
            } else {
                $this->logger->add($this->args['spider_id'] . ':copy-cjcx-' . ($tryTimes) . ':上货参数:' . StringHelper::jsonEncode($this->copyData));
                $this->_writeLog('RESPONSE_DECODE:' . json_encode($this->copyData));
                $responseCommit = (new Goods())->pddGoodsAdd($this->copyData, $this->args['mall_id']);
                if (!isset($responseCommit['goods_add_response'])) {
                    $subCode = @$responseCommit['error_response']['sub_code'];
                    if (isset($subCode) && $subCode != '2000000') {
                        $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                        throw new CopyException($errStr);
                    }
                    ConsoleHelper::runInfo('上货删除部分sku后失败，并重试第' . ($tryTimes) . '次');
                    $tryTimes++;
                    sleep(1);
                    continue;
                }
                $responseData = $responseCommit['goods_add_response'];
                break;
            }
        }
        if ($responseData == null) {
            throw new CopyException('各sku规格值加和数量超过限制，重试多次后依然失败');
        }
        return $responseData;
    }

    /**
     * sku 部分sku信息不完整补全
     * @param int $copyStatus
     * @return mixed|null
     * @throws CopyException
     * @throws ServicesException
     */
    private function retrySkuLimitError(int $copyStatus)
    {
        $responseData = null;
        $tryTimes = 0;
        $skuListArr = StringHelper::jsonDecode($this->copyData['sku_list']);
        while ($tryTimes <= $this->retryTimes) {
            list($skuListArr, $this->skuDataTree) = PddSku::reduceSkuLimitData($skuListArr, $this->skuDataTree);
            $this->copyData['sku_list'] = StringHelper::jsonEncode($skuListArr);
            if ($copyStatus == 2) {
                $this->logger->add($this->args['spider_id'] . ':copy-cjcx-' . ($tryTimes) . ':上货参数:' . StringHelper::jsonEncode($this->copyData));
                $responseCommit = $this->goodsIsv->pddGoodsEditGoodsCommit($this->copyData, $this->args['mall_id']);
                if (!isset($responseCommit['goods_update_response'])) {
                    $subCode = @$responseCommit['error_response']['sub_code'];
                    if (isset($subCode) && $subCode != '2000000') {
                        $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                        throw new CopyException($errStr);
                    }
                    ConsoleHelper::runInfo('上货草稿箱,删除部分sku后失败，并重试第' . ($tryTimes) . '次');
                    $tryTimes++;
                    sleep(1);
                    continue;
                }
                $responseData = $responseCommit['goods_update_response'];
                break;
            } else {
                $this->logger->add($this->args['spider_id'] . ':copy-cjcx-' . ($tryTimes) . ':上货参数:' . StringHelper::jsonEncode($this->copyData));
                $this->_writeLog('RESPONSE_DECODE:' . json_encode($this->copyData));
                $responseCommit = (new Goods())->pddGoodsAdd($this->copyData, $this->args['mall_id']);
                if (!isset($responseCommit['goods_add_response'])) {
                    $subCode = @$responseCommit['error_response']['sub_code'];
                    if (isset($subCode) && $subCode != '2000000') {
                        $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                        $this->_writeLog2(json_encode($this->copyData));
                        throw new CopyException($errStr);
                    }
                    ConsoleHelper::runInfo('上货删除部分sku后失败，并重试第' . ($tryTimes) . '次');
                    $tryTimes++;
                    sleep(1);
                    continue;
                }
                $responseData = $responseCommit['goods_add_response'];
                break;
            }
        }
        if ($responseData == null) {
            $this->_writeLog3(json_encode($this->copyData), '@runtime/api/isverror3/');
            throw new CopyException('各sku规格值加和数量超过限制，重试多次后依然失败');
        }
        return $responseData;
    }

    /**
     * sku 价格倍数不正确补救措施，将价格高的sku设置为最低的sku价格 库存设置为空，并且设置为已下架
     * @param int $copyStatus
     * @return array|null
     * @throws ServicesException
     * @throws CopyException
     */
    private function retrySkuPriceError(int $copyStatus)
    {
        $responseData = null;
        $tryTimes = 0;
        $skuListArr = StringHelper::jsonDecode($this->copyData['sku_list']);
        while ($tryTimes <= $this->retryTimes) {
            $multiPrice = ArrayHelper::getColumn($skuListArr, 'multi_price');
            $maxPrice = max($multiPrice);
            $minPrice = min($multiPrice);
            foreach ($skuListArr as $k => $sku) {
                if ($sku['multi_price'] == $maxPrice) {
                    if ($maxPrice > $this->copyData['market_price']) {
                        $this->copyData['market_price'] = $sku['price'] + 1;
                    }
                    $skuListArr[$k]['multi_price'] = $minPrice;
                    $skuListArr[$k]['price'] = $minPrice + 100;
                    $skuListArr[$k]['is_onsale'] = 0;
                    $skuListArr[$k]['quantity'] = 0;
                }
                if ($sku['multi_price'] < $minPrice) {
                    $skuListArr[$k]['multi_price'] = $minPrice;
                    $skuListArr[$k]['price'] = $minPrice + 100;
                    $skuListArr[$k]['is_onsale'] = 0;
                    $skuListArr[$k]['quantity'] = 0;
                }
            }
            $multiPrice = ArrayHelper::getColumn($skuListArr, 'multi_price');
            $singlePrice = ArrayHelper::getColumn($skuListArr, 'price');
            if (min($multiPrice) * 5 < $this->copyData['market_price']) {
                $this->copyData['market_price'] = max($singlePrice) + 1;
            }
            $this->copyData['sku_list'] = StringHelper::jsonEncode($skuListArr);
            if ($copyStatus == 2) {
                $this->logger->add($this->args['spider_id'] . ':copy-' . ($tryTimes) . ':上货参数:' . StringHelper::jsonEncode($this->copyData));
                $responseCommit = $this->goodsIsv->pddGoodsEditGoodsCommit($this->copyData, $this->args['mall_id']);
                if (!isset($responseCommit['goods_update_response'])) {
                    $subCode = @$responseCommit['error_response']['sub_code'];
                    if (isset($subCode) && $subCode != 'isv.invalid-parameter:price-gap-is-over-range') {
                        $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                        if ($errStr == 'sku数量和规格乘积不一致' || $errStr == '部分sku的规格信息不完整' || $errStr == '规格值加和数量超过限制，请删除' || $errStr == '规格数目不可超过2') {
                            ;
                            $responseCommit = $this->errorHandler($responseCommit['error_response']['sub_code'], $copyStatus, $responseCommit, $errStr);
                            if (isset($responseCommit['goods_commit_id'])) {
                                return $responseCommit;
                                break;
                            }
                        } else {
                            throw new CopyException($errStr);
                        }
                    }
                    ConsoleHelper::runInfo('上货草稿箱,将最高价格：' . $maxPrice . '，调整为：' . $minPrice . '失败，并重试第' . ($tryTimes) . '次');
                    $tryTimes++;
                    sleep(1);
                    continue;
                }
                $responseData = $responseCommit['goods_update_response'];
                break;
            } else {
                $this->logger->add($this->args['spider_id'] . ':copy-' . ($tryTimes) . ':上货参数:' . StringHelper::jsonEncode($this->copyData));
                $responseCommit = (new Goods())->pddGoodsAdd($this->copyData, $this->args['mall_id']);
                if (!isset($responseCommit['goods_add_response'])) {
                    $subCode = @$responseCommit['error_response']['sub_code'];
                    $this->_writeLog(json_encode($this->copyData));
                    if (isset($subCode) && $subCode != 'isv.invalid-parameter:price-gap-is-over-range') {
                        $errStr = $responseCommit['error_response']['error_msg'] ?? '请求服务异常';
                        if ($errStr == 'sku数量和规格乘积不一致' || $errStr == '部分sku的规格信息不完整' || $errStr == '规格值加和数量超过限制，请删除' || $errStr == '规格数目不可超过2') {
                            ;
                            $responseCommit = $this->errorHandler($responseCommit['error_response']['sub_code'], $copyStatus, $responseCommit, $errStr);
                            if (isset($responseCommit['goods_commit_id'])) {
                                return $responseCommit;
                                break;
                            }
                        } else {
                            throw new CopyException($errStr);
                        }
                    }
                    ConsoleHelper::runInfo('上货在售,将最高价格：' . $maxPrice . '，调整为：' . $minPrice . '失败，并重试第' . ($tryTimes) . '次');
                    $tryTimes++;
                    sleep(1);
                    continue;
                }
                $responseData = $responseCommit['goods_add_response'];
                break;
            }
        }
        if ($responseData == null) {
            throw new CopyException('各sku的拼单价相差过大，重试多次后依然失败');
        }
        return $responseData;
    }


    /**
     * 基础设置
     * @since 修复 请求参数不为空的bug
     * @throws CopyException
     * @throws ServicesException
     * @throws \yii\base\Exception
     */
    public function basicSetting()
    {
        $basicFilter = new PddFilterBasic($this->logger, $this->args['spider_id']);

        /**
         * 类目设置
         */
        $this->_showLog('开始类目匹配');
        if (!isset($this->sourceData->extend_data['cid']) || empty($this->sourceData->extend_data['cid'])) {
            throw new CopyException('商品不存在或已下架');
        }
        $this->copyData['cat_id'] = $basicFilter->setCid($this->sourceData, $this->filter, $this->goodsIsv, $this->args['mall_id']);
        $this->logInfo->cid = $this->copyData['cat_id'];
        $this->_showLog('类目匹配完成，匹配的类目id为' . $this->copyData['cat_id']);
        /**
         * 检查类目是否允许
         */
        $result = $this->copyServer->checkCatIsAuthorization($this->copyData['cat_id'], $this->args['uid'], $this->args['mall_id']);

        if (!$result) {
            throw new CopyException('类目检测未通过');
        }

        /**
         * 商家编码
         */
        $goodsNo = '';
        $attrArr = @$this->sourceData->extend_data['attr'];
        if (isset($attrArr) && is_array($attrArr)) {
            foreach ($attrArr as $k => $attr) {
                if ($attr['key'] == '货号') {
                    $goodsNo = $attr['value'];
                    break;
                }
            }
        }
        $this->copyData['out_goods_id'] = PddSpec::outGoodsId(
            $goodsNo, $this->filter->settings['product_no'],
            $this->sourceData->plat_id,
            PlatformConst::transPlatformPy($this->sourceData->platform)
        );

        //拿到品牌属性值
        $brandVal = PddSpec::getBrandVal($this->sourceData->extend_data['attr']);
        if(is_array($brandVal)){
            $brandVal = $brandVal[0];
        }
        /**
         * 标题设置
         */
        $this->copyData['goods_name'] = PddSpec::setTitle($this->logInfo->title, $this->filter->settings['title'], $brandVal);


        /**
         * 配置项中如果有水印，先将水印下载到本地,水印一律压缩处理成指定宽高尺寸
         * @since 附件不从db中读取，读取过多的mysql内容会导致mysql 出现异常情况
         */

        if (isset($this->filter->settings['images']['main_avatar_setting']['avatar_url']) && !empty($this->filter->settings['images']['main_avatar_setting']['avatar_url'])) {

//            $avatarMain = ComImages::findOne(['id'=>$this->filter->settings['images']['main_avatar_id']]);
            $resultDownLoadImg = ImagesHelper::downloadByUrl($this->filter->settings['images']['main_avatar_setting']['avatar_url']);

            if ($resultDownLoadImg) {
//                list($mainAvatarPath,$name) = ImagesHelper::saveBoldToPath(stripslashes($avatarMain->binarydata),$avatarMain->file_md5.'.'.$avatarMain->type);
                list($mainAvatarPath, $name) = $resultDownLoadImg;
                list($width, $height) = getimagesize($mainAvatarPath);
                if ($mainAvatarPath && $width > 200) {
                    if ($this->avatarWidth < $width) {
                        $height = (intval($this->avatarWidth) * $height) / $width;
                    }
                    $mainAvatarPath = ImagesHelper::thumbImg($mainAvatarPath, $name, $this->avatarWidth, $height);
                    $this->mainWater = $mainAvatarPath;
                } else {
                    $this->mainWater = $mainAvatarPath;
                }
            }
        }

        if (isset($this->filter->settings['images']['detail_avatar_setting']['avatar_url']) && !empty($this->filter->settings['images']['detail_avatar_setting']['avatar_url'])) {
//            $avatarDetail = ComImages::findOne(['id'=>$this->filter->settings['images']['detail_avatar_id']]);
            $resultDownLoadImg = ImagesHelper::downloadByUrl($this->filter->settings['images']['detail_avatar_setting']['avatar_url']);
            if ($resultDownLoadImg) {
                list($detailAvatar, $detailName) = $resultDownLoadImg;
//                list($detailAvatar,$detailName) = ImagesHelper::saveBoldToPath(stripslashes($avatarDetail->binarydata),$avatarDetail->file_md5.'.'.$avatarDetail->type);

                list($width, $height) = getimagesize($detailAvatar);
                if ($detailAvatar && $width > 200) {
                    if ($this->avatarWidth < $width) {
                        $height = (intval($this->avatarWidth) * $height) / $width;
                    }
                    $detailAvatar = ImagesHelper::thumbImg($detailAvatar, $detailName, $this->avatarWidth, $height);
                    $this->detailWater = $detailAvatar;
                } else {
                    $this->detailWater = $detailAvatar;
                }
            }
        }

        /**
         * 适配一些预设字段
         */
        $copyData = $basicFilter->presetField($this->sourceData, $this->filter);


        $this->copyData = array_merge($this->copyData, $copyData);
        /**
         * 轮播图处理
         */
        $carouselData = $basicFilter->carousel($this->sourceData, $this->copyServer, $this->filter, $this->args['mall_id'], $this->mainWater);

        $this->copyData = array_merge($this->copyData, $carouselData);


        $this->logInfo->title = $this->copyData['goods_name'];


        /**
         * 属性适配
         */
        $this->setSpecAndSku();


        if (isset($this->copyData['carousel_gallery'][0])) $this->logInfo->main_pic = $this->copyData['carousel_gallery'][0];


        /**
         * 详情图适配
         */
        $detailData = $basicFilter->detail($this->sourceData, $this->copyServer, $this->filter, $this->args['mall_id'], $this->detailWater);
        if ($detailData) {
            $this->copyData = array_merge($this->copyData, $detailData);
        } else {
            $this->_showLog('详情图为空，使用轮播图作为详情图使用');
            //详情图为空，则将轮播图作为详情图使用
            $this->copyData['detail_gallery'] = StringHelper::jsonEncode($this->copyData['carousel_gallery']);
        }
        /**
         * 商品详情
         */
        $this->copyData['goods_desc'] = $basicFilter->goodsDesc($this->sourceData);

        //轮播图序列化下
        $this->copyData['carousel_gallery'] = StringHelper::jsonEncode($this->copyData['carousel_gallery']);

    }


    /**
     * 通过类目匹配出对应的属性 和sku信息
     * @throws \yii\base\Exception
     */
    protected function setSpecAndSku()
    {
        $specInfo = $this->copyServer->getSpecByCid($this->copyData['cat_id'], $this->args['mall_id']);
        $tryTimes = 0;
        while ($tryTimes <= $this->retryTimes) {
            $skuMapInfo = $this->goodsIsv->pddGoodsSpecGet($this->copyData['cat_id'], $this->args['mall_id']);
            if (isset($skuMapInfo['goods_spec_list'])) {
                break;
            } else {
                $tryTimes++;
                sleep(1);
                $this->_showLog('goods_spec_list获取失败正在重试第' . $tryTimes . '次');
                $this->_writeLog('RESPONSE_DECODE:' . json_encode($skuMapInfo));
            }
        }


        /**
         * sku别名适配
         */
        $aliasSkuList = PddSpec::skuValueSettings($this->sourceData->extend_data['skus'], $this->filter->settings['sku']);

        /**
         * 处理源数据sku 信息
         */
        $tripSkuImg = PddSpec::tripSkuImg($this->sourceData->extend_data['sku_img']);
        $tripSkuList = PddSpec::tripSkuList($aliasSkuList);


        $skuData = PddSpec::getSkuBySkuList($tripSkuList, $tripSkuImg);
        $this->copyData['goods_properties'] = [];
        if ($specInfo) {
            list($parentSpecList, $childSpecList) = PddSpec::getPropsParentAndChild($specInfo['properties']);

            /**
             * 非销售属性适配
             */
            $properties = $this->_notSalesTolerant($parentSpecList, $childSpecList);
            /**
             * 最后拼装非销售属性参数
             */
            foreach ($properties as $p => $prop) {
                $tmp = [];
                $tmp['ref_pid'] = $prop['ref_pid'];
                $tmp['value'] = $prop['value'];
                if ($prop['vid']) {
                    $tmp['vid'] = $prop['vid'];
                }
                //属性模板id
                $tmp['template_pid'] = $prop['template_pid'];
                //存在上级属性
//            if(isset($prop['parent_spec_id']))
//            {
//                $tmp['parent_spec_id'] = $prop['parent_spec_id'];
//            }
                if (!empty($prop['value_unit'])) {
                    $tmp['value_unit'] = $prop['value_unit'];
                }
                array_push($this->copyData['goods_properties'], $tmp);
            }
        }
        $this->copyData['goods_properties'] = StringHelper::jsonEncode($this->copyData['goods_properties']);


        /**
         * 销售属性适配
         */
        $skuData = $this->_salesProp($skuData, $skuMapInfo);

        $this->skuDataTree = $skuData;
        /**
         * 销售属性，适配sku
         */
        $this->_setSku($skuData, $tripSkuList);


    }


    /**
     * 非销售属性适配
     * @param $parentSpecList
     * @param $childSpecList
     * @return array|void
     * @throws ServicesException
     */
    private function _notSalesTolerant($parentSpecList, $childSpecList)
    {
        $emptyProperties = $properties = [];

        $sourceAttr = $this->sourceData->extend_data['attr'];
//        print_r($this->sourceData->extend_data['attr']);
        /**
         * 先匹配一级属性
         */
        foreach ($parentSpecList as $k => $prop) {
            switch ($prop['is_sale']) {
                case true: //销售属性
                    break;
                default: //非销售属性
                    $notSaleProp = PddSpec::notSalesProp($prop, $sourceAttr, $this->filter->settings['default_value'], $this->filter);
                    if (!empty($notSaleProp)) {
                        array_push($properties, $notSaleProp);
                    } else {
                        //foreach 循环继续
                        if ($prop['name_alias'] == '品牌') continue 2;
                        array_push($emptyProperties, $prop);
                    }
            }
        }
        /**
         * 检查下一级属性中没有匹配上的非销售属性中是否含有必填项，如果有必填项默认选择第一个作为值
         */
        if (count($emptyProperties)) {
            foreach ($emptyProperties as $k => $e_prop) {
                if (isset($e_prop['required']) && $e_prop['required'] == true) {
                    $eItems = isset($e_prop['values'][0]) && is_array($e_prop['values'][0]) ? $e_prop['values'][0] : null;
                    if ($eItems) {
                        array_push($properties, [
                            'vid' => $eItems['vid'],
                            'value' => $eItems['value'],
                            'out_property_name' => $e_prop['name_alias'],
                            'ref_pid' => $e_prop['id'],
                            'template_pid' => $e_prop['id'],
                            'value_unit' => $e_prop['value_unit'],
                        ]);
                        unset($emptyProperties[$k]);
                    } else {
                        $eItems = null;
                        if (isset($e_prop['min_value'])) {
                            switch (@$e_prop['control_type']) {
                                case 12:
                                    $eItems = $e_prop['min_value'] . ',' . $e_prop['min_value'];
                                    break;
                                case 13:
                                    $eItems = $e_prop['min_value'] . ',' . $e_prop['min_value'] . ',' . $e_prop['min_value'];
                                    break;
                            }
                        }
                        if ($eItems) {
                            array_push($properties, [
                                'vid' => 0,
                                'value' => $eItems,
                                'out_property_name' => $e_prop['name_alias'],
                                'ref_pid' => $e_prop['id'],
                                'template_pid' => $e_prop['id'],
                                'value_unit' => $e_prop['value_unit'],
                            ]);
                            unset($emptyProperties[$k]);
                        }
                    }
                }

            }
        }


        /**
         * 适配下是否选择了匹配不上适配所有
         */
        if (isset($this->filter->settings['attr']['auto_select']) && in_array($this->filter->settings['attr']['auto_select'], [2, 3])) {
            switch ($this->filter->settings['attr']['auto_select']) {
                case 2: //随机一项填写
                    foreach ($emptyProperties as $e => $props) {
                        if (isset($props['values']) && is_array($props['values'])) {
                            $checkedKey = array_rand($props['values']);
                            $checkedV = $props['values'][$checkedKey];

                            array_push($properties, [
                                'ref_pid' => $props['ref_pid'],
                                'template_pid' => $props['id'],
                                'value' => $checkedV['value'],
                                'out_property_name' => $props['name_alias'],
                                'vid' => $checkedV['vid'],
                                'value_unit' => '',
                            ]);
                        }

                    }
                    break;
                case 3: //选择第一项填写
                    foreach ($emptyProperties as $e => $props) {
                        if (isset($props['values']) && is_array($props['values'])) {
                            $checkedV = $props['values'][0];
                            array_push($properties, [
                                'ref_pid' => $props['ref_pid'],
                                'template_pid' => $props['id'],
                                'value' => $checkedV['value'],
                                'out_property_name' => $props['name_alias'],
                                'vid' => $checkedV['vid'],
                                'value_unit' => '',
                            ]);
                        }

                    }
                    break;
            }
        }

        /**
         * 是否设置了属性强制预设
         */
        $filterDefault = @$this->filter->settings['default_value']['attr'];
        if (isset($filterDefault) && is_array($filterDefault)) {
            $properties = PddPreset::attrCompulsory($parentSpecList, $properties, $filterDefault);
        }

        /**
         * 匹配子属性
         */
        $properties = PddSpec::notSaleSpecChildFilter($childSpecList, $properties, $sourceAttr, $this->filter->settings['default_value']);

        return $properties;
    }

    /**
     * 设置sku 复制参数
     * @param array $skuData
     * @param array $tripSkuList
     * @throws \yii\base\Exception
     */
    private function _setSku(array $skuData, array $tripSkuList)
    {

//        print_r($this->sourceData->extend_data);
        $transSkuId = PddSpec::transSkuId($skuData);
        $transSkuImg = PddSpec::transSkuImg(PddSpec::tripSkuImg($this->sourceData->extend_data['sku_img']));

        $copyStatus = @$this->filter->settings['basic']['copy_goods_status'];
        $this->_showLog('开始处理sku附件');

        //图片是否压缩
        $compress = $this->filter->settings['compress']['pic_compress_percent'] ?? null;
        $imgSetting = [];
        $imgSetting['is_cut'] = true;
        if (isset($compress) && $compress < 100 && $compress >= 50) {
            $imgSetting['is_compress'] = true;
            $imgSetting['compress_percent'] = $compress;
        }


        /**
         * 颜色图是否打水印设置
         */
        if (isset($this->filter->settings['images']['main_pic_watermark_long']) && !empty($this->filter->settings['images']['main_pic_watermark_long'])) {
            $imgSetting = array_merge(CopyHelper::formatWaterSetting($this->filter->settings['images']['main_avatar_setting'], $this->mainWater));
//            $imgSetting['water_path'] = $this->mainWater;
//            $imgSetting['water_position'] = 1; //右下角
            $imgSetting['is_water'] = true;
        }
        /**
         * sku 没有图片不需要做处理
         */
        if (count($transSkuImg)) {
            /**
             * 协程下载图片
             */
            $wg = new WaitGroup();
            $transSkuImg = array_unique($transSkuImg);
            foreach ($transSkuImg as $k => $skuImg) {
                if ($tmpImgRet = substr($skuImg, 0, 2) == '//') {
                    $skuImg = 'https:' . $skuImg;
                }
                $tmpImg = explode('.', $skuImg);
                $ext = end($tmpImg);
                if (!in_array($ext, Yii::$app->params['pddImageExt'])) continue;
                $wg->add();
                go(function () use ($wg, $skuImg, $imgSetting, $k, &$transSkuImg) {
                    ConsoleHelper::runInfo('正在下载SKU图片:' . $skuImg);
                    $imgInfo = PddSpec::processImage($skuImg, $imgSetting);
                    if ($imgInfo) {
                        //轮播图要求 等宽高且大于480px,大小1M内
                        list($processImg, $width, $height, $size) = $imgInfo;
                        if ($width != $height || $width < 480 || ImagesHelper::sizeToM($size) > 1) {
                            unset($transSkuImg[$k]);
                            PddSpec::delLocalImg($processImg);
                        } else {
                            $transSkuImg[$k] = $processImg;
                        }
                    } else {
                        unset($transSkuImg[$k]);
                    }
                });
                $wg->done();
            }
            $wg->wait();
            /**
             * 上传sku图
             */
            foreach ($transSkuImg as $k => $skuImg) {
                if ($skuImg) {
                    if (strpos($skuImg, 'gif') !== false) {
                        continue;
                    } else {
                        $this->_showLog('正在上传[' . $skuImg . ']图片');

                        $transSkuImg[$k] = $this->copyServer->uploadImageToPdd($skuImg, $this->args['mall_id']);
                    }
                }
            }
        }
        $this->_showLog('sku附件处理完成');
        $priceSetting = $this->filter->settings['price'];
        $this->copyData['sku_list'] = $pricesArr = $multiArr = $salePriceArr = [];
        $mallLogistics = new PddMallLogisticsDao();
        $mallLogisticsInfo = $mallLogistics->getInfoByTmplateId($this->filter->settings['basic']['cost_template_id']);
        $costType = 0;
        if ($mallLogisticsInfo) {
            $costType = $mallLogisticsInfo->cost_type;
        }
        foreach ($tripSkuList as $k => $item) {
            $propertiesList = json_decode($item['properties_name'], true);
            $tmp = [];
            $tmp['thumb_url'] = '';
            $spec_id_list = [];
            foreach ($propertiesList as $p => $prop) {
                if (!empty($transSkuId[$prop])) {
                    array_push($spec_id_list, $transSkuId[$prop]);
                }

                if (!empty($transSkuImg[$prop])) {
                    $tmp['thumb_url'] = $transSkuImg[$prop];
                }
            }
            /**
             * 便于后面比较
             * @since 不能对生成的sku_list 做排序操作，会造成sku 名称混乱情况
             */
//            sort($spec_id_list);

            /**
             * sku图为空，默认将商品主图作为sku图
             */
            if (empty($tmp['thumb_url']) && isset($this->copyData['carousel_gallery'])) {
                $this->_showLog('SKU图为空，补救措施:将商品主图第一张作为sku图');
                if (is_array($this->copyData['carousel_gallery'])) {
                    if (isset($this->copyData['carousel_gallery'][0])) {
                        $tmp['thumb_url'] = $this->copyData['carousel_gallery'][0];
                    }
                } else {
                    $tmp['thumb_url'] = json_decode($this->copyData['carousel_gallery'], true)[0];
                }

            }
            $calPrice = $priceSetting['price_product_setting'] == 1 ? $item['sale_price'] : $item['price'];
            $tmp['limit_quantity'] = $this->filter->settings['basic']['buy_limit'];
            $tmp['out_source_sku_id'] = $item['skuId'];

            //设置待售，全部sku变更成已下架
            if ($copyStatus == 1) {
                $tmp['is_onsale'] = 0;
            } else {
                $tmp['is_onsale'] = 1; //sku上架状态，0-已下架，1-上架中
            }

            $tmp['quantity'] = $item['stock'];
            $tmp['out_sku_sn'] = '';
            $tmp['spec_id_list'] = json_encode($spec_id_list, JSON_UNESCAPED_UNICODE);
            $tmp['weight'] = 1000;


            $tmp['multi_price'] = PddSpec::multiPrice($calPrice, $priceSetting);
            $tmp['price'] = PddSpec::price(AmountHelper::fenToYuan($tmp['multi_price']), $priceSetting);
            //单买价小于等于团购价 则将单买价格+1元
            if ($tmp['price'] < $tmp['multi_price'] + 100) $tmp['price'] = $tmp['multi_price'] + 100;
            array_push($pricesArr, $tmp['price']);
            array_push($salePriceArr, $item['sale_price']);
            array_push($multiArr, $tmp['multi_price']);
            array_push($this->copyData['sku_list'], $tmp);
        }

        /**
         * 最低价sku设置
         * @since  使用货源销售价最小值计算
         */
        if (isset($priceSetting['calculation_min_sku_checked']) &&
            $priceSetting['calculation_min_sku_checked'] == true &&
            isset($priceSetting['min_sku_price_stock']) &&
            $priceSetting['min_sku_price_stock'] > 0 &&
            count($multiArr) && count($salePriceArr)) {
            $minMulti = min($multiArr);
            //找到最低价的sku 将sku 的价格重新设置下，并且重新设置下最低价的sku库存信息
            foreach ($this->copyData['sku_list'] as $k => $item) {
                if ($item['multi_price'] == $minMulti) {
                    //就是元，不需要再转换成分,只需要设置一个 即可
                    $saleMinMulti = min($salePriceArr);
                    $this->copyData['sku_list'][$k]['multi_price'] = PddSpec::lowestSkuPrice($saleMinMulti, $priceSetting);
                    if (!empty($priceSetting['min_sku_price_stock'])) {
                        $this->copyData['sku_list'][$k]['quantity'] = intval($priceSetting['min_sku_price_stock']);
                    }
                    break;
                }
            }
        }


        /**
         * 如果不存在sku，则创建一个单品sku
         */
        if (count($this->copyData['sku_list'])) {
            $maxMulti = AmountHelper::fenToYuan(max($multiArr));
            $this->copyData['market_price'] = PddSpec::marketPrice($maxMulti, $priceSetting);

            $maxSinglePrice = max($pricesArr);

            //容错下市场价小于单买价问题
            if ($this->copyData['market_price'] <= $maxSinglePrice) {
                $maxMulti = AmountHelper::yuanTofen($maxMulti);

                if ($maxMulti < $maxSinglePrice) {
                    $this->copyData['market_price'] = $maxSinglePrice + 100;
                } else {
                    $this->copyData['market_price'] = $maxMulti * 5;
                }
            }


            if (!PddSku::checkSkuNum($skuData, $this->copyData['sku_list'])) {
                $this->_showLog('sku乘积不一致，自动补全身下的sku信息，并设置为下架状态');
                $this->copyData['sku_list'] = PddSku::autoFullSku($skuData, $this->copyData['sku_list']);
            }
            $this->copyData['sku_list'] = StringHelper::jsonEncode($this->copyData['sku_list']);
        } else {
            //无sku 处理方式
            $singleSku = [];
            $calPrice = $this->sourceData->extend_data['prices'] / 100;
            $singleSku['limit_quantity'] = $this->filter->settings['basic']['buy_limit'];
            $singleSku['out_source_sku_id'] = '';
            //设置待售，全部sku变更成已下架
            if ($copyStatus == 1) {
                $singleSku['is_onsale'] = 0;
            } else {
                $singleSku['is_onsale'] = 1; //sku上架状态，0-已下架，1-上架中
            }
            $singleSku['quantity'] = 0;
            $singleSku['out_sku_sn'] = '';
            $singleSku['spec_id_list'] = '[]';
            $singleSku['weight'] = 1000;
            $singleSku['multi_price'] = PddSpec::multiPrice($calPrice, $priceSetting);
            $singleSku['price'] = PddSpec::price(AmountHelper::fenToYuan($singleSku['multi_price']), $priceSetting);


            //单买价小于等于团购价 则将单买价格+1元
            if ($singleSku['price'] < $singleSku['multi_price'] + 100) $singleSku['price'] = $singleSku['multi_price'] + 100;

            $maxMulti = AmountHelper::fenToYuan($singleSku['multi_price']);
            $this->copyData['market_price'] = PddSpec::marketPrice($maxMulti, $priceSetting);

            //市场价小于单买价
            if ($this->copyData['market_price'] <= $singleSku['price']) {
                $this->copyData['market_price'] = $singleSku['multi_price'] * 5;
            }
            //商品无sku
            $this->copyData['sku_list'] = [$singleSku];
            $this->copyData['sku_list'] = StringHelper::jsonEncode($this->copyData['sku_list']);
        }

    }


    /**
     * 销售属性处理
     * @param array $skuData
     * @param array $skuMapInfo
     * @return
     * @throws \common\exception\ServicesException
     * @throws CopyException
     * @throws \yii\base\Exception
     */
    protected function _salesProp(array $skuData, array $skuMapInfo)
    {
        $matchSku = $skuMatchData = [];

        foreach ($skuData as $s => $sku) {
            /**
             * 相似关键词映射匹配下
             */
            foreach ($sku as $_s => $val) {
                foreach ($skuMapInfo['goods_spec_list'] as $g => $gSpec) {
                    if (PddSpec::compareStrSimilar($s, $gSpec['parent_spec_name'])) {
                        unset($skuData[$s]);
                        $responseSpecId = $this->goodsIsv->pddGoodsSpecIdGet($gSpec['parent_spec_id'], $val['name'], $this->args['mall_id']);
                        if (!isset($responseSpecId['spec_id'])) {
                            $responseSpecId = $this->goodsIsv->pddGoodsSpecIdGet($gSpec['parent_spec_id'], mb_substr($val['name'], 0, 20) . rand(0, 100), $this->args['mall_id']);
                        }
                        if (isset($responseSpecId['spec_id'])) {
                            $skuMatchData[$s][$_s]['props']['spec_id'] = $responseSpecId['spec_id'];
                            $skuMatchData[$s][$_s]['props']['parent_spec_id'] = $responseSpecId['parent_spec_id'];
                            $skuMatchData[$s][$_s]['props']['value'] = $responseSpecId['spec_name'];
                            $skuMatchData[$s][$_s]['name'] = $val['name'];
                            array_push($matchSku, $gSpec['parent_spec_name']);
                        }
                        if (!isset($responseSpecId['spec_id'])) {
                            throw new ServicesException($responseSpecId['error_msg']);
                        }
                    }
                }
            }
        }

        /**
         * 兜底方案，没有匹配上的sku 按照sku属性列表从上往下挨个匹配
         * 型号
         */
        if (count($skuData)) {

            $goodsSpecList = $skuMapInfo['goods_spec_list'];

            /**
             * 剔除已经匹配上的属性
             */
            foreach ($goodsSpecList as $k => $item) {
                if (in_array($item['parent_spec_name'], $matchSku)) {
                    unset($goodsSpecList[$k]);
                }
            }

            /**
             * 数组下标从0开始
             */
            $goodsSpecList = array_values($goodsSpecList);
            /**
             * 依次取sku属性列表中从上到下匹配相关属性
             */
            $checkedNum = 0;
            foreach ($skuData as $k => $skuList) {
                $parentSpecId = $goodsSpecList[$checkedNum]['parent_spec_id'];
                $parentSpecName = $goodsSpecList[$checkedNum]['parent_spec_name'];

                $this->_showLog('SKU属性名称匹配失败,匹配属性名称:[' . $k . '],程序使用:[' . $parentSpecName . '] 替代');
                $this->writeMappingError($this->args['spider_id'] . ':SKU属性名称匹配失败,匹配属性名称:[' . $k . ']');
                foreach ($skuList as $g => $val) {
                    $responseSpecId = $this->goodsIsv->pddGoodsSpecIdGet($parentSpecId, $val['name'], $this->args['mall_id']);
                    if (!isset($responseSpecId['spec_id'])) {
                        $responseSpecId = $this->goodsIsv->pddGoodsSpecIdGet($parentSpecId, mb_substr($val['name'], 0, 20) . rand(0, 100), $this->args['mall_id']);
                    }
                    if (isset($responseSpecId['spec_id'])) {
                        $skuMatchData[$k][$g]['props']['spec_id'] = $responseSpecId['spec_id'];
                        $skuMatchData[$k][$g]['props']['parent_spec_id'] = $responseSpecId['parent_spec_id'];
                        $skuMatchData[$k][$g]['props']['value'] = $responseSpecId['spec_name'];
                        $skuMatchData[$k][$g]['name'] = $val['name'];
                    }
                    if (!isset($responseSpecId['spec_id'])) {
                        throw new ServicesException($responseSpecId['error_msg']);
                    }
                }
                unset($goodsSpecList[$checkedNum]);
                $checkedNum++;
            }
        }
        return $skuMatchData;
    }


    /**
     * 跳过设置
     * @inheritDoc
     * @throws JumpException
     * @throws \yii\base\Exception
     */
    public function filter()
    {

        $filterJump = new PddFilterJump($this->sourceData, $this->filter, $this->args['mall_id'], $this->args['uid']);

        //全局跳过
        $filterJump->globalSetting();


        //跳过重复，相同货号、季节跳过
        $filterJump->jumpRepeat();


        //跳过其他一些阀值设置
        $filterJump->jumpThreshold();
    }


    /**
     * 采集log目录初始化
     * @return bool|string
     * @throws \yii\base\Exception
     */
    protected function _createFilePath()
    {
        $path = Yii::getAlias('@runtime/job/copy/');

        //目录如果不存就先创建目录
        if (!is_dir($path)) {
            FileHelper::createDirectory($path);
        }

        return $path;
    }

    /**
     * 输出错误信息
     * @param string $msg
     */
    protected function _showLog(string $msg)
    {
        ConsoleHelper::runInfo($this->args['spider_id'] . ':copy:' . $msg);
        $this->logger->add($this->args['spider_id'] . ':copy:' . $msg);
    }

    /**
     * 输出错误信息
     * @param string $msg
     */
    /**
     * 文件日志记录
     * @param $msg
     * @throws ServicesException
     */
    private function _writeLog($msg)
    {

        try {
            $path = Yii::getAlias('@runtime/api/isverror/');

            //目录如果不存就先创建目录
            if (!is_dir($path)) {
                FileHelper::createDirectory($path);
            }

            $cp = fopen($path . 'log-' . date('YmdHi') . '.log', "a+");
            $txt = "【" . date('Y-m-d H:i:s', time()) . "】---" . $msg . "\r\n";
            fwrite($cp, $txt);
            fclose($cp);
        } catch (Exception $e) {
            throw new ServicesException($e->getMessage());
        }

    }

    private function _writeLog2($msg)
    {

        try {
            $path = Yii::getAlias('@runtime/api/isverror2/');

            //目录如果不存就先创建目录
            if (!is_dir($path)) {
                FileHelper::createDirectory($path);
            }

            $cp = fopen($path . 'log-' . date('YmdHi') . '.log', "a+");
            $txt = "【" . date('Y-m-d H:i:s', time()) . "】---" . $msg . "\r\n";
            fwrite($cp, $txt);
            fclose($cp);
        } catch (Exception $e) {
            throw new ServicesException($e->getMessage());
        }

    }

    private function _writeLog3($msg, $url)
    {

        try {
            $path = Yii::getAlias($url);

            //目录如果不存就先创建目录
            if (!is_dir($path)) {
                FileHelper::createDirectory($path);
            }

            $cp = fopen($path . 'log-' . date('YmdHi') . '.log', "a+");
            $txt = "【" . date('Y-m-d H:i:s', time()) . "】---" . $msg . "\r\n";
            fwrite($cp, $txt);
            fclose($cp);
        } catch (Exception $e) {
            throw new ServicesException($e->getMessage());
        }

    }
}